package string;

/**
 * 字符串String
 * 内部使用一个char数组保存所有的字符，每一个字符为2字节，存的是该字符Unicode编码
 * 字符串是不变队形，一点创建内容不可改变，若改变会创建新对象
 */

public class StringDemo {
    public static void main(String[] args) {
        /*
        字符串常量池
        java在堆内存中开辟了一段空间用于缓存所有使用字面量形式创建的字符串对象
        并在后期再次使用该字面量创建字符串时重用对象，避免内存中堆积大量内容一样
        的字符串对象来减小内存开销。
         */
        String s1 = "123abc";
        String s2 = "123abc";
        //地址相同，说明s2重用了s1对象
        System.out.println(s1==s2);//true
        String s3 = "123abc";
        System.out.println(s1==s3);//true

        String s4 = new String("123abc");//new会产生新对象
        System.out.println("s4:"+s4);
        System.out.println(s1==s4);//false

        /*
        通常我们判断字符串都是比较内容，因此应当使用字符串的equals方法
         */
        System.out.println(s1.equals(s4));//true
        /*
        由于字符串是不变对象，百变内容会产生新对象
         */

        s1=s1+"!"; //生成一个新的字符串对象123abc！
        System.out.println("s1:"+s1);//123abc
        System.out.println("s2:"+s2);//123abc
        System.out.println(s1==s2);//false a1,s2亦将不在指向同一对象了

        /*
        这是触发了一个编译期的特性
        编译期在编译期间若遇到几个计算表达式，发现在编译期可以确定结果时就会进行计算
        并将结果编译到class文件中，这样以来JVM每次执行字节码文件就无须再计算了。
        下面的代码会被编译器改为：
        String s5 = “123abc”；
        也因此s5会重用常量池中的对象，所以地址与s2相同
         */
        String s5 = "123"+"abc";
        System.out.println("s5:"+s5);
        System.out.println(s2==s5);

        String s = "123";
        String s6 = s+"abc";
        System.out.println("s6:"+s6);
        System.out.println(s2 == s6);

        String s7 = 1+2+3+"abc";
        System.out.println(s2==s7);//false

        String s8 = 1+'2'+3+"abc";
        System.out.println(s2==s8);//false

        String s9 = 1+"2"+3+"abc";
        System.out.println(s2==s9);//true
    }
}
